home *** CD-ROM | disk | FTP | other *** search
- /* convert.c - convert RImage to Pixmap
- *
- * Raster graphics library
- *
- * Copyright (c) 1997-2000 Alfredo K. Kojima
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- #include <config.h>
-
-
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
-
- #include <assert.h>
-
- #ifdef BENCH
- #include "bench.h"
- #endif
-
- #include "wraster.h"
-
- #ifdef XSHM
- extern Pixmap R_CreateXImageMappedPixmap(RContext *context, RXImage *ximage);
-
- #endif
-
-
- #ifdef ASM_X86
- extern void x86_PseudoColor_32_to_8(unsigned char *image,
- unsigned char *ximage,
- char *err, char *nerr,
- short *ctable,
- int dr, int dg, int db,
- unsigned long *pixels,
- int cpc,
- int width, int height,
- int bytesPerPixel,
- int line_offset);
- #endif /* ASM_X86 */
-
- #ifdef ASM_X86_MMX
-
- extern int x86_check_mmx();
-
- extern void x86_mmx_TrueColor_32_to_16(unsigned char *image,
- unsigned short *ximage,
- short *err, short *nerr,
- short *rtable, short *gtable,
- short *btable,
- int dr, int dg, int db,
- unsigned int roffs,
- unsigned int goffs,
- unsigned int boffs,
- int width, int height,
- int line_offset);
-
-
-
- #endif /* ASM_X86_MMX */
-
-
-
- typedef struct RConversionTable {
- unsigned short table[256];
- unsigned short index;
-
- struct RConversionTable *next;
- } RConversionTable;
-
-
- typedef struct RStdConversionTable {
- unsigned int table[256];
-
- unsigned short mult;
- unsigned short max;
-
- struct RStdConversionTable *next;
- } RStdConversionTable;
-
-
-
- static RConversionTable *conversionTable = NULL;
- static RStdConversionTable *stdConversionTable = NULL;
-
-
- static unsigned short*
- computeTable(unsigned short mask)
- {
- RConversionTable *tmp = conversionTable;
- int i;
-
- while (tmp) {
- if (tmp->index == mask)
- break;
- tmp = tmp->next;
- }
-
- if (tmp)
- return tmp->table;
-
- tmp = (RConversionTable *)malloc(sizeof(RConversionTable));
- if (tmp == NULL)
- return NULL;
-
- for (i=0;i<256;i++)
- tmp->table[i] = (i*mask + 0x7f)/0xff;
-
- tmp->index = mask;
- tmp->next = conversionTable;
- conversionTable = tmp;
- return tmp->table;
- }
-
-
- static unsigned int*
- computeStdTable(unsigned int mult, unsigned int max)
- {
- RStdConversionTable *tmp = stdConversionTable;
- unsigned int i;
-
- while (tmp) {
- if (tmp->mult == mult && tmp->max == max)
- break;
- tmp = tmp->next;
- }
-
- if (tmp)
- return tmp->table;
-
- tmp = (RStdConversionTable *)malloc(sizeof(RStdConversionTable));
- if (tmp == NULL)
- return NULL;
-
- for (i=0; i<256; i++) {
- tmp->table[i] = (i*max)/0xff * mult;
- }
- tmp->mult = mult;
- tmp->max = max;
-
- tmp->next = stdConversionTable;
- stdConversionTable = tmp;
-
- return tmp->table;
- }
-
- /***************************************************************************/
-
-
- static void
- convertTrueColor_generic(RXImage *ximg, RImage *image,
- char *err, char *nerr,
- const short *rtable,
- const short *gtable,
- const short *btable,
- const int dr, const int dg, const int db,
- const unsigned short roffs,
- const unsigned short goffs,
- const unsigned short boffs)
- {
- char *terr;
- int x, y, r, g, b;
- int pixel;
- int rer, ger, ber;
- unsigned char *ptr = image->data;
- int channels = image->format == RRGBAFormat ? 4 : 3;
-
- /* convert and dither the image to XImage */
- for (y=0; y<image->height; y++) {
- nerr[0] = 0;
- nerr[1] = 0;
- nerr[2] = 0;
- for (x=0; x<image->width; x++, ptr+=channels) {
-
- /* reduce pixel */
- pixel = *ptr + err[x];
- if (pixel<0) pixel=0; else if (pixel>0xff) pixel=0xff;
- r = rtable[pixel];
- /* calc error */
- rer = pixel - r*dr;
-
- /* reduce pixel */
- pixel = *(ptr+1) + err[x+1];
- if (pixel<0) pixel=0; else if (pixel>0xff) pixel=0xff;
- g = gtable[pixel];
- /* calc error */
- ger = pixel - g*dg;
-
- /* reduce pixel */
- pixel = *(ptr+2) + err[x+2];
- if (pixel<0) pixel=0; else if (pixel>0xff) pixel=0xff;
- b = btable[pixel];
- /* calc error */
- ber = pixel - b*db;
-
-
- pixel = (r<<roffs) | (g<<goffs) | (b<<boffs);
- XPutPixel(ximg->image, x, y, pixel);
-
- /* distribute error */
- r = (rer*3)/8;
- g = (ger*3)/8;
- b = (ber*3)/8;
- /* x+1, y */
- err[x+3*1]+=r;
- err[x+1+3*1]+=g;
- err[x+2+3*1]+=b;
- /* x, y+1 */
- nerr[x]+=r;
- nerr[x+1]+=g;
- nerr[x+2]+=b;
- /* x+1, y+1 */
- nerr[x+3*1]=rer-2*r;
- nerr[x+1+3*1]=ger-2*g;
- nerr[x+2+3*1]=ber-2*b;
- }
- /* skip to next line */
- terr = err;
- err = nerr;
- nerr = terr;
- }
- }
-
-
-
-
- static RXImage*
- image2TrueColor(RContext *ctx, RImage *image)
- {
- RXImage *ximg;
- unsigned short rmask, gmask, bmask;
- unsigned short roffs, goffs, boffs;
- unsigned short *rtable, *gtable, *btable;
- int channels = (image->format == RRGBAFormat ? 4 : 3);
-
- ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height);
- if (!ximg) {
- return NULL;
- }
-
- roffs = ctx->red_offset;
- goffs = ctx->green_offset;
- boffs = ctx->blue_offset;
-
- rmask = ctx->visual->red_mask >> roffs;
- gmask = ctx->visual->green_mask >> goffs;
- bmask = ctx->visual->blue_mask >> boffs;
-
- rtable = computeTable(rmask);
- gtable = computeTable(gmask);
- btable = computeTable(bmask);
-
- if (rtable==NULL || gtable==NULL || btable==NULL) {
- RErrorCode = RERR_NOMEMORY;
- RDestroyXImage(ctx, ximg);
- return NULL;
- }
-
-
- #ifdef BENCH
- cycle_bench(1);
- #endif
-
- if (ctx->attribs->render_mode==RBestMatchRendering) {
- int ofs, r, g, b;
- int x, y;
- unsigned long pixel;
- unsigned char *ptr = image->data;
-
- /* fake match */
- #ifdef DEBUG
- puts("true color match");
- #endif
- for (y=0, ofs=0; y < image->height; y++) {
- for (x=0; x < image->width; x++, ofs+=channels-3) {
- /* reduce pixel */
- r = rtable[ptr[ofs++]];
- g = gtable[ptr[ofs++]];
- b = btable[ptr[ofs++]];
- pixel = (r<<roffs) | (g<<goffs) | (b<<boffs);
- XPutPixel(ximg->image, x, y, pixel);
- }
- }
- } else {
- /* dither */
- const int dr=0xff/rmask;
- const int dg=0xff/gmask;
- const int db=0xff/bmask;
-
- #ifdef DEBUG
- puts("true color dither");
- #endif
-
- #ifdef ASM_X86_MMX
- if (ctx->depth == 16 && image->format == RRGBAFormat
- && x86_check_mmx()) {
- short *err;
- short *nerr;
-
- err = malloc(8*(image->width+3));
- nerr = malloc(8*(image->width+3));
- if (!err || !nerr) {
- if (nerr)
- free(nerr);
- RErrorCode = RERR_NOMEMORY;
- RDestroyXImage(ctx, ximg);
- return NULL;
- }
- memset(err, 0, 8*(image->width+3));
- memset(nerr, 0, 8*(image->width+3));
-
- x86_mmx_TrueColor_32_to_16(image->data,
- (unsigned short*)ximg->image->data,
- err+8, nerr+8,
- rtable, gtable, btable,
- dr, dg, db,
- roffs, goffs, boffs,
- image->width, image->height,
- ximg->image->bytes_per_line - 2*image->width);
-
- free(err);
- free(nerr);
- } else
- #endif /* ASM_X86_MMX */
- {
- char *err;
- char *nerr;
- int ch = image->format == RRGBAFormat ? 4 : 3;
-
- err = malloc(ch*(image->width+2));
- nerr = malloc(ch*(image->width+2));
- if (!err || !nerr) {
- if (nerr)
- free(nerr);
- RErrorCode = RERR_NOMEMORY;
- RDestroyXImage(ctx, ximg);
- return NULL;
- }
-
- memset(err, 0, ch*(image->width+2));
- memset(nerr, 0, ch*(image->width+2));
-
- convertTrueColor_generic(ximg, image, err, nerr,
- rtable, gtable, btable,
- dr, dg, db, roffs, goffs, boffs);
- free(err);
- free(nerr);
- }
-
- }
-
- #ifdef BENCH
- cycle_bench(0);
- #endif
-
- return ximg;
- }
-
-
- /***************************************************************************/
-
- static void
- convertPseudoColor_to_8(RXImage *ximg, RImage *image,
- char *err, char *nerr,
- const short *rtable,
- const short *gtable,
- const short *btable,
- const int dr, const int dg, const int db,
- unsigned long *pixels,
- int cpc)
- {
- char *terr;
- int x, y, r, g, b;
- int pixel;
- int rer, ger, ber;
- unsigned char *ptr = image->data;
- unsigned char *optr = ximg->image->data;
- int channels = image->format == RRGBAFormat ? 4 : 3;
- int cpcpc = cpc*cpc;
-
- /* convert and dither the image to XImage */
- for (y=0; y<image->height; y++) {
- nerr[0] = 0;
- nerr[1] = 0;
- nerr[2] = 0;
- for (x=0; x<image->width*3; x+=3, ptr+=channels) {
-
- /* reduce pixel */
- pixel = *ptr + err[x];
- if (pixel<0) pixel=0; else if (pixel>0xff) pixel=0xff;
- r = rtable[pixel];
- /* calc error */
- rer = pixel - r*dr;
-
- /* reduce pixel */
- pixel = *(ptr+1) + err[x+1];
- if (pixel<0) pixel=0; else if (pixel>0xff) pixel=0xff;
- g = gtable[pixel];
- /* calc error */
- ger = pixel - g*dg;
-
- /* reduce pixel */
- pixel = *(ptr+2) + err[x+2];
- if (pixel<0) pixel=0; else if (pixel>0xff) pixel=0xff;
- b = btable[pixel];
- /* calc error */
- ber = pixel - b*db;
-
- *optr++ = pixels[r*cpcpc + g*cpc + b];
-
- /* distribute error */
- r = (rer*3)/8;
- g = (ger*3)/8;
- b = (ber*3)/8;
-
- /* x+1, y */
- err[x+3*1]+=r;
- err[x+1+3*1]+=g;
- err[x+2+3*1]+=b;
- /* x, y+1 */
- nerr[x]+=r;
- nerr[x+1]+=g;
- nerr[x+2]+=b;
- /* x+1, y+1 */
- nerr[x+3*1]=rer-2*r;
- nerr[x+1+3*1]=ger-2*g;
- nerr[x+2+3*1]=ber-2*b;
- }
- /* skip to next line */
- terr = err;
- err = nerr;
- nerr = terr;
-
- optr += ximg->image->bytes_per_line - image->width;
- }
- }
-
-
-
- static RXImage*
- image2PseudoColor(RContext *ctx, RImage *image)
- {
- RXImage *ximg;
- register int x, y, r, g, b;
- unsigned char *ptr;
- unsigned long pixel;
- const int cpc=ctx->attribs->colors_per_channel;
- const unsigned short rmask = cpc-1; /* different sizes could be used */
- const unsigned short gmask = rmask; /* for r,g,b */
- const unsigned short bmask = rmask;
- unsigned short *rtable, *gtable, *btable;
- const int cpccpc = cpc*cpc;
- int channels = image->format == RRGBAFormat ? 4 : 3;
-
- ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height);
- if (!ximg) {
- return NULL;
- }
-
- ptr = image->data;
-
- /* Tables are same at the moment because rmask==gmask==bmask. */
- rtable = computeTable(rmask);
- gtable = computeTable(gmask);
- btable = computeTable(bmask);
-
- if (rtable==NULL || gtable==NULL || btable==NULL) {
- RErrorCode = RERR_NOMEMORY;
- RDestroyXImage(ctx, ximg);
- return NULL;
- }
-
- if (ctx->attribs->render_mode == RBestMatchRendering) {
- /* fake match */
- #ifdef DEBUG
- printf("pseudo color match with %d colors per channel\n", cpc);
- #endif
- for (y=0; y<image->height; y++) {
- for (x=0; x<image->width; x++, ptr+=channels-1) {
- /* reduce pixel */
- r = rtable[*ptr++];
- g = gtable[*ptr++];
- b = btable[*ptr++];
- pixel = r*cpccpc + g*cpc + b;
- /*data[ofs] = ctx->colors[pixel].pixel;*/
- XPutPixel(ximg->image, x, y, ctx->colors[pixel].pixel);
- }
- }
- } else {
- /* dither */
- char *err;
- char *nerr;
- const int dr=0xff/rmask;
- const int dg=0xff/gmask;
- const int db=0xff/bmask;
-
-
- #ifdef DEBUG
- printf("pseudo color dithering with %d colors per channel\n", cpc);
- #endif
- err = malloc(4*(image->width+3));
- nerr = malloc(4*(image->width+3));
- if (!err || !nerr) {
- if (nerr)
- free(nerr);
- RErrorCode = RERR_NOMEMORY;
- RDestroyXImage(ctx, ximg);
- return NULL;
- }
- memset(err, 0, 4*(image->width+3));
- memset(nerr, 0, 4*(image->width+3));
-
- /*#ifdef ASM_X86*/
- #if 0
- x86_PseudoColor_32_to_8(image->data, ximg->image->data,
- err+4, nerr+4,
- rtable,
- dr, dg, db, ctx->pixels, cpc,
- image->width, image->height,
- channels,
- ximg->image->bytes_per_line - image->width);
- #else
- convertPseudoColor_to_8(ximg, image, err+4, nerr+4,
- rtable, gtable, btable,
- dr, dg, db, ctx->pixels, cpc);
- #endif
-
- free(err);
- free(nerr);
- }
-
- return ximg;
- }
-
-
- /*
- * For standard colormap
- */
- static RXImage*
- image2StandardPseudoColor(RContext *ctx, RImage *image)
- {
- RXImage *ximg;
- register int x, y, r, g, b;
- unsigned char *ptr;
- unsigned long pixel;
- unsigned char *data;
- unsigned int *rtable, *gtable, *btable;
- unsigned int base_pixel = ctx->std_rgb_map->base_pixel;
- int channels = image->format == RRGBAFormat ? 4 : 3;
- /*register unsigned char maxrgb = 0xff;*/
-
- ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height);
- if (!ximg) {
- return NULL;
- }
-
- ptr = image->data;
-
- data = (unsigned char *)ximg->image->data;
-
-
- rtable = computeStdTable(ctx->std_rgb_map->red_mult,
- ctx->std_rgb_map->red_max);
-
- gtable = computeStdTable(ctx->std_rgb_map->green_mult,
- ctx->std_rgb_map->green_max);
-
- btable = computeStdTable(ctx->std_rgb_map->blue_mult,
- ctx->std_rgb_map->blue_max);
-
- if (rtable==NULL || gtable==NULL || btable==NULL) {
- RErrorCode = RERR_NOMEMORY;
- RDestroyXImage(ctx, ximg);
- return NULL;
- }
-
-
- if (ctx->attribs->render_mode == RBestMatchRendering) {
- for (y=0; y<image->height; y++) {
- for (x=0; x<image->width; x++, ptr+=channels-3) {
- /* reduce pixel */
- pixel = (rtable[*ptr++] + gtable[*ptr++]
- + btable[*ptr++] + base_pixel) & 0xffffffff;
-
- XPutPixel(ximg->image, x, y, pixel);
- }
- }
- } else {
- /* dither */
- short *err, *nerr;
- short *terr;
- int rer, ger, ber;
- int x1, ofs;
-
- #ifdef DEBUG
- printf("pseudo color dithering with %d colors per channel\n", cpc);
- #endif
- err = (short*)malloc(3*(image->width+2)*sizeof(short));
- nerr = (short*)malloc(3*(image->width+2)*sizeof(short));
- if (!err || !nerr) {
- if (nerr)
- free(nerr);
- RErrorCode = RERR_NOMEMORY;
- RDestroyXImage(ctx, ximg);
- return NULL;
- }
- for (x=0, x1=0; x<image->width*3; x1+=channels-3) {
- err[x++] = ptr[x1++];
- err[x++] = ptr[x1++];
- err[x++] = ptr[x1++];
- }
- err[x++] = err[x++] = err[x++] = 0;
- /* convert and dither the image to XImage */
- for (y=0, ofs=0; y<image->height; y++) {
- if (y<image->height-1) {
- int x1;
- for (x=0, x1=(y+1)*image->width*channels;
- x<image->width*3;
- x1+=channels-3) {
- nerr[x++] = ptr[x1++];
- nerr[x++] = ptr[x1++];
- nerr[x++] = ptr[x1++];
- }
- /* last column */
- x1-=channels;
- nerr[x++] = ptr[x1++];
- nerr[x++] = ptr[x1++];
- nerr[x++] = ptr[x1++];
- }
- for (x=0; x<image->width*3; x+=3, ofs++) {
- /* reduce pixel */
- if (err[x]>0xff) err[x]=0xff; else if (err[x]<0) err[x]=0;
- if (err[x+1]>0xff) err[x+1]=0xff; else if (err[x+1]<0) err[x+1]=0;
- if (err[x+2]>0xff) err[x+2]=0xff; else if (err[x+2]<0) err[x+2]=0;
-
- r = rtable[err[x]];
- g = gtable[err[x+1]];
- b = btable[err[x+2]];
-
- pixel = r + g + b;
-
- data[ofs] = base_pixel + pixel;
-
- /* calc error */
- rer = err[x] - (ctx->colors[pixel].red>>8);
- ger = err[x+1] - (ctx->colors[pixel].green>>8);
- ber = err[x+2] - (ctx->colors[pixel].blue>>8);
-
- /* distribute error */
- err[x+3*1]+=(rer*7)/16;
- err[x+1+3*1]+=(ger*7)/16;
- err[x+2+3*1]+=(ber*7)/16;
-
- nerr[x]+=(rer*5)/16;
- nerr[x+1]+=(ger*5)/16;
- nerr[x+2]+=(ber*5)/16;
-
- if (x>0) {
- nerr[x-3*1]+=(rer*3)/16;
- nerr[x-3*1+1]+=(ger*3)/16;
- nerr[x-3*1+2]+=(ber*3)/16;
- }
-
- nerr[x+3*1]+=rer/16;
- nerr[x+1+3*1]+=ger/16;
- nerr[x+2+3*1]+=ber/16;
- }
- /* skip to next line */
- terr = err;
- err = nerr;
- nerr = terr;
-
- ofs += ximg->image->bytes_per_line - image->width;
- }
- free(err);
- free(nerr);
- }
- ximg->image->data = (char*)data;
-
- return ximg;
- }
-
-
-
- static RXImage*
- image2GrayScale(RContext *ctx, RImage *image)
- {
- RXImage *ximg;
- register int x, y, g;
- unsigned char *ptr;
- const int cpc=ctx->attribs->colors_per_channel;
- unsigned short gmask;
- unsigned short *table;
- unsigned char *data;
- int channels = image->format == RRGBAFormat ? 4 : 3;
-
- /*register unsigned char maxrgb = 0xff;*/
-
- ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height);
- if (!ximg) {
- return NULL;
- }
-
- ptr = image->data;
-
- data = (unsigned char *)ximg->image->data;
-
- if (ctx->vclass == StaticGray)
- gmask = (1<<ctx->depth) - 1; /* use all grays */
- else
- gmask = cpc*cpc*cpc-1;
-
- table = computeTable(gmask);
-
- if (table==NULL) {
- RErrorCode = RERR_NOMEMORY;
- RDestroyXImage(ctx, ximg);
- return NULL;
- }
-
- if (ctx->attribs->render_mode == RBestMatchRendering) {
- /* fake match */
- #ifdef DEBUG
- printf("grayscale match with %d colors per channel\n", cpc);
- #endif
- for (y=0; y<image->height; y++) {
- for (x=0; x<image->width; x++) {
- /* reduce pixel */
- g = table[(*ptr++ * 30 + *ptr++ * 59 + *ptr++ * 11)/100];
-
- /*data[ofs] = ctx->colors[g].pixel;*/
- XPutPixel(ximg->image, x, y, ctx->colors[g].pixel);
- }
- }
- } else {
- /* dither */
- short *gerr;
- short *ngerr;
- short *terr;
- int ger;
- const int dg=0xff/gmask;
-
- #ifdef DEBUG
- printf("grayscale dither with %d colors per channel\n", cpc);
- #endif
- gerr = (short*)malloc((image->width+2)*sizeof(short));
- ngerr = (short*)malloc((image->width+2)*sizeof(short));
- if (!gerr || !ngerr) {
- if (ngerr)
- free(ngerr);
- RErrorCode = RERR_NOMEMORY;
- RDestroyXImage(ctx, ximg);
- return NULL;
- }
- for (x=0; x<image->width; x++) {
- gerr[x] = (ptr[x*3]*30 + ptr[x*3+1]*59 + ptr[x*3+2]*11)/100;
- }
- gerr[x] = 0;
- /* convert and dither the image to XImage */
- for (y=0; y<image->height; y++) {
- if (y<image->height-1) {
- int x1;
- for (x=0, x1=(y+1)*image->width*3;
- x<image->width;
- x1+=channels-3) {
- ngerr[x] = (ptr[x1++]*30 + ptr[x1++]*59 + ptr[x1++]*11)/100;
- }
- /* last column */
- x1-=channels;
- ngerr[x] = (ptr[x1++]*30 + ptr[x1++]*59 + ptr[x1++]*11)/100;
- }
- for (x=0; x<image->width; x++) {
- /* reduce pixel */
- if (gerr[x]>0xff) gerr[x]=0xff; else if (gerr[x]<0) gerr[x]=0;
-
- g = table[gerr[x]];
-
- /*data[ofs] = ctx->colors[g].pixel;*/
- XPutPixel(ximg->image, x, y, ctx->colors[g].pixel);
- /* calc error */
- ger = gerr[x] - g*dg;
-
- /* distribute error */
- g = (ger*3)/8;
- /* x+1, y */
- gerr[x+1]+=g;
- /* x, y+1 */
- ngerr[x]+=g;
- /* x+1, y+1 */
- ngerr[x+1]+=ger-2*g;
- }
- /* skip to next line */
- terr = gerr;
- gerr = ngerr;
- ngerr = terr;
- }
- free(gerr);
- free(ngerr);
- }
- ximg->image->data = (char*)data;
-
- return ximg;
- }
-
-
- static RXImage*
- image2Bitmap(RContext *ctx, RImage *image, int threshold)
- {
- RXImage *ximg;
- unsigned char *alpha;
- int x, y;
-
- ximg = RCreateXImage(ctx, 1, image->width, image->height);
- if (!ximg) {
- return NULL;
- }
- alpha = image->data+3;
-
- for (y = 0; y < image->height; y++) {
- for (x = 0; x < image->width; x++) {
- XPutPixel(ximg->image, x, y, (*alpha <= threshold ? 0 : 1));
- alpha+=4;
- }
- }
-
- return ximg;
- }
-
-
-
- int
- RConvertImage(RContext *context, RImage *image, Pixmap *pixmap)
- {
- RXImage *ximg=NULL;
- #ifdef XSHM
- Pixmap tmp;
- #endif
-
- assert(context!=NULL);
- assert(image!=NULL);
- assert(pixmap!=NULL);
-
- /* clear error message */
- if (context->vclass == TrueColor) {
-
- ximg = image2TrueColor(context, image);
-
- } else if (context->vclass == PseudoColor
- || context->vclass == StaticColor) {
-
- #ifdef BENCH
- cycle_bench(1);
- #endif
- if (context->attribs->standard_colormap_mode != RIgnoreStdColormap)
- ximg = image2StandardPseudoColor(context, image);
- else
- ximg = image2PseudoColor(context, image);
- #ifdef BENCH
- cycle_bench(0);
- #endif
- } else if (context->vclass == GrayScale || context->vclass == StaticGray) {
-
- ximg = image2GrayScale(context, image);
- }
-
- if (!ximg) {
- return False;
- }
-
-
- *pixmap = XCreatePixmap(context->dpy, context->drawable, image->width,
- image->height, context->depth);
-
- #ifdef XSHM
- if (context->flags.use_shared_pixmap && ximg->is_shared)
- tmp = R_CreateXImageMappedPixmap(context, ximg);
- else
- tmp = None;
- if (tmp) {
- /*
- * We have to copy the shm Pixmap into a normal Pixmap because
- * otherwise, we would have to control when Pixmaps are freed so
- * that we can detach their shm segments. This is a problem if the
- * program crash, leaving stale shared memory segments in the
- * system (lots of them). But with some work, we can optimize
- * things and remove this XCopyArea. This will require
- * explicitly freeing all pixmaps when exiting or restarting
- * wmaker.
- */
- XCopyArea(context->dpy, tmp, *pixmap, context->copy_gc, 0, 0,
- image->width, image->height, 0, 0);
- XFreePixmap(context->dpy, tmp);
- } else {
- RPutXImage(context, *pixmap, context->copy_gc, ximg, 0, 0, 0, 0,
- image->width, image->height);
- }
- #else /* !XSHM */
- RPutXImage(context, *pixmap, context->copy_gc, ximg, 0, 0, 0, 0,
- image->width, image->height);
- #endif /* !XSHM */
-
- RDestroyXImage(context, ximg);
-
- return True;
- }
-
-
- int
- RConvertImageMask(RContext *context, RImage *image, Pixmap *pixmap,
- Pixmap *mask, int threshold)
- {
- GC gc;
- XGCValues gcv;
- RXImage *ximg=NULL;
-
- assert(context!=NULL);
- assert(image!=NULL);
- assert(pixmap!=NULL);
- assert(mask!=NULL);
-
- if (!RConvertImage(context, image, pixmap))
- return False;
-
- if (image->format==RRGBFormat) {
- *mask = None;
- return True;
- }
-
- ximg = image2Bitmap(context, image, threshold);
-
- if (!ximg) {
- return False;
- }
- *mask = XCreatePixmap(context->dpy, context->drawable, image->width,
- image->height, 1);
- gcv.foreground = context->black;
- gcv.background = context->white;
- gcv.graphics_exposures = False;
- gc = XCreateGC(context->dpy, *mask, GCForeground|GCBackground
- |GCGraphicsExposures, &gcv);
- RPutXImage(context, *mask, gc, ximg, 0, 0, 0, 0,
- image->width, image->height);
- RDestroyXImage(context, ximg);
-
- return True;
- }
-
-
- Bool
- RGetClosestXColor(RContext *context, RColor *color, XColor *retColor)
- {
- if (context->vclass == TrueColor) {
- unsigned short rmask, gmask, bmask;
- unsigned short roffs, goffs, boffs;
- unsigned short *rtable, *gtable, *btable;
-
- roffs = context->red_offset;
- goffs = context->green_offset;
- boffs = context->blue_offset;
-
- rmask = context->visual->red_mask >> roffs;
- gmask = context->visual->green_mask >> goffs;
- bmask = context->visual->blue_mask >> boffs;
-
- rtable = computeTable(rmask);
- gtable = computeTable(gmask);
- btable = computeTable(bmask);
-
- retColor->pixel = (rtable[color->red]<<roffs) |
- (gtable[color->green]<<goffs) | (btable[color->blue]<<boffs);
-
- retColor->red = color->red << 8;
- retColor->green = color->green << 8;
- retColor->blue = color->blue << 8;
- retColor->flags = DoRed|DoGreen|DoBlue;
-
- } else if (context->vclass == PseudoColor
- || context->vclass == StaticColor) {
-
- if (context->attribs->standard_colormap_mode != RIgnoreStdColormap) {
- unsigned int *rtable, *gtable, *btable;
-
- rtable = computeStdTable(context->std_rgb_map->red_mult,
- context->std_rgb_map->red_max);
-
- gtable = computeStdTable(context->std_rgb_map->green_mult,
- context->std_rgb_map->green_max);
-
- btable = computeStdTable(context->std_rgb_map->blue_mult,
- context->std_rgb_map->blue_max);
-
- if (rtable==NULL || gtable==NULL || btable==NULL) {
- RErrorCode = RERR_NOMEMORY;
- return False;
- }
-
- retColor->pixel = (rtable[color->red]
- + gtable[color->green]
- + btable[color->blue]
- + context->std_rgb_map->base_pixel) & 0xffffffff;
- retColor->red = color->red<<8;
- retColor->green = color->green<<8;
- retColor->blue = color->blue<<8;
- retColor->flags = DoRed|DoGreen|DoBlue;
-
- } else {
- const int cpc=context->attribs->colors_per_channel;
- const unsigned short rmask = cpc-1; /* different sizes could be used */
- const unsigned short gmask = rmask; /* for r,g,b */
- const unsigned short bmask = rmask;
- unsigned short *rtable, *gtable, *btable;
- const int cpccpc = cpc*cpc;
- int index;
-
- rtable = computeTable(rmask);
- gtable = computeTable(gmask);
- btable = computeTable(bmask);
-
- if (rtable==NULL || gtable==NULL || btable==NULL) {
- RErrorCode = RERR_NOMEMORY;
- return False;
- }
- index = rtable[color->red]*cpccpc + gtable[color->green]*cpc
- + btable[color->blue];
- *retColor = context->colors[index];
- }
-
- } else if (context->vclass == GrayScale || context->vclass == StaticGray) {
-
- const int cpc = context->attribs->colors_per_channel;
- unsigned short gmask;
- unsigned short *table;
- int index;
-
- if (context->vclass == StaticGray)
- gmask = (1<<context->depth) - 1; /* use all grays */
- else
- gmask = cpc*cpc*cpc-1;
-
- table = computeTable(gmask);
- if (!table)
- return False;
-
- index = table[(color->red*30 + color->green*59 + color->blue*11)/100];
-
- *retColor = context->colors[index];
- } else {
- RErrorCode = RERR_INTERNAL;
- return False;
- }
-
- return True;
- }
-
-